GskRenderNode *node,
RenderOpBuilder *builder);
-typedef enum
-{
- RENDER_FULL,
- RENDER_SCISSOR
-} RenderMode;
-
struct _GskGLRenderer
{
GskRenderer parent_instance;
} profile_timers;
#endif
- RenderMode render_mode;
+ cairo_region_t *render_region;
gboolean has_buffers : 1;
};
g_clear_object (&self->gl_context);
}
-static GdkDrawingContext *
-gsk_gl_renderer_begin_draw_frame (GskRenderer *renderer,
- const cairo_region_t *update_area)
-{
- GskGLRenderer *self = GSK_GL_RENDERER (renderer);
- cairo_region_t *damage;
- GdkDrawingContext *result;
- GdkRectangle whole_surface;
- GdkSurface *surface;
-
- surface = gsk_renderer_get_surface (renderer);
- whole_surface = (GdkRectangle) {
- 0, 0,
- gdk_surface_get_width (surface) * self->scale_factor,
- gdk_surface_get_height (surface) * self->scale_factor
- };
- damage = gdk_gl_context_get_damage (self->gl_context);
- cairo_region_union (damage, update_area);
-
- if (cairo_region_contains_rectangle (damage, &whole_surface) == CAIRO_REGION_OVERLAP_IN)
- {
- self->render_mode = RENDER_FULL;
- }
- else
- {
- GdkRectangle extents;
-
- cairo_region_get_extents (damage, &extents);
- cairo_region_union_rectangle (damage, &extents);
-
- if (gdk_rectangle_equal (&extents, &whole_surface))
- self->render_mode = RENDER_FULL;
- else
- self->render_mode = RENDER_SCISSOR;
- }
-
- result = gdk_surface_begin_draw_frame (surface,
- GDK_DRAW_CONTEXT (self->gl_context),
- damage);
-
- cairo_region_destroy (damage);
-
- return result;
-}
-
static void
gsk_gl_renderer_resize_viewport (GskGLRenderer *self,
const graphene_rect_t *viewport)
static void
gsk_gl_renderer_setup_render_mode (GskGLRenderer *self)
{
- switch (self->render_mode)
- {
- case RENDER_FULL:
+ if (self->render_region == NULL)
+ {
glDisable (GL_SCISSOR_TEST);
- break;
-
- case RENDER_SCISSOR:
- {
- GdkDrawingContext *context = gsk_renderer_get_drawing_context (GSK_RENDERER (self));
- GdkSurface *surface = gsk_renderer_get_surface (GSK_RENDERER (self));
- cairo_region_t *clip = gdk_drawing_context_get_clip (context);
- cairo_rectangle_int_t extents;
- int surface_height;
-
- /* Fall back to RENDER_FULL */
- if (clip == NULL)
- {
- glDisable (GL_SCISSOR_TEST);
- return;
- }
-
- g_assert (cairo_region_num_rectangles (clip) == 1);
-
- surface_height = gdk_surface_get_height (surface) * self->scale_factor;
-
- /*cairo_region_get_extents (clip, &extents);*/
- cairo_region_get_rectangle (clip, 0, &extents);
+ }
+ else
+ {
+ GdkSurface *surface = gsk_renderer_get_surface (GSK_RENDERER (self));
+ cairo_rectangle_int_t extents;
+ int surface_height;
- glEnable (GL_SCISSOR_TEST);
- glScissor (extents.x * self->scale_factor,
- surface_height - (extents.height * self->scale_factor) - (extents.y * self->scale_factor),
- extents.width * self->scale_factor,
- extents.height * self->scale_factor);
+ g_assert (cairo_region_num_rectangles (self->render_region) == 1);
- cairo_region_destroy (clip);
- break;
- }
+ surface_height = gdk_surface_get_height (surface) * self->scale_factor;
+ cairo_region_get_rectangle (self->render_region, 0, &extents);
- default:
- g_assert_not_reached ();
- break;
- }
+ glEnable (GL_SCISSOR_TEST);
+ glScissor (extents.x * self->scale_factor,
+ surface_height - (extents.height * self->scale_factor) - (extents.y * self->scale_factor),
+ extents.width * self->scale_factor,
+ extents.height * self->scale_factor);
+ }
}
g_return_val_if_fail (self->gl_context != NULL, NULL);
- self->render_mode = RENDER_FULL;
width = ceilf (viewport->size.width);
height = ceilf (viewport->size.height);
}
static void
-gsk_gl_renderer_render (GskRenderer *renderer,
- GskRenderNode *root)
+gsk_gl_renderer_render (GskRenderer *renderer,
+ GskRenderNode *root,
+ const cairo_region_t *update_area)
{
GskGLRenderer *self = GSK_GL_RENDERER (renderer);
- GdkSurface *surface = gsk_renderer_get_surface (renderer);
graphene_rect_t viewport;
+ cairo_region_t *damage;
+ GdkDrawingContext *context;
+ GdkRectangle whole_surface;
+ GdkSurface *surface;
if (self->gl_context == NULL)
return;
+ surface = gsk_renderer_get_surface (renderer);
+ whole_surface = (GdkRectangle) {
+ 0, 0,
+ gdk_surface_get_width (surface) * self->scale_factor,
+ gdk_surface_get_height (surface) * self->scale_factor
+ };
+ damage = gdk_gl_context_get_damage (self->gl_context);
+ cairo_region_union (damage, update_area);
+
+ if (cairo_region_contains_rectangle (damage, &whole_surface) == CAIRO_REGION_OVERLAP_IN)
+ {
+ self->render_region = NULL;
+ }
+ else
+ {
+ GdkRectangle extents;
+
+ cairo_region_get_extents (damage, &extents);
+ cairo_region_union_rectangle (damage, &extents);
+
+ if (gdk_rectangle_equal (&extents, &whole_surface))
+ self->render_region = NULL;
+ else
+ self->render_region = cairo_region_reference (damage);
+ }
+
+ context = gdk_surface_begin_draw_frame (surface,
+ GDK_DRAW_CONTEXT (self->gl_context),
+ damage);
+
+ cairo_region_destroy (damage);
+ if (self->render_region)
+ {
+ damage = gdk_drawing_context_get_clip (context);
+ cairo_region_union (self->render_region, damage);
+ cairo_region_destroy (damage);
+ }
+
self->scale_factor = gdk_surface_get_scale_factor (surface);
gdk_gl_context_make_current (self->gl_context);
gdk_gl_context_make_current (self->gl_context);
gsk_gl_renderer_clear_tree (self);
+
+ gdk_surface_end_draw_frame (surface, context);
+
+ g_clear_pointer (&self->render_region, cairo_region_destroy);
}
static void
renderer_class->realize = gsk_gl_renderer_realize;
renderer_class->unrealize = gsk_gl_renderer_unrealize;
- renderer_class->begin_draw_frame = gsk_gl_renderer_begin_draw_frame;
renderer_class->render = gsk_gl_renderer_render;
renderer_class->render_texture = gsk_gl_renderer_render_texture;
}
}
-static GdkDrawingContext *
-gsk_broadway_renderer_begin_draw_frame (GskRenderer *renderer,
- const cairo_region_t *update_area)
-{
- cairo_region_t *region;
- GdkDrawingContext *result;
- cairo_rectangle_int_t whole_surface;
- GdkSurface *surface;
-
- surface = gsk_renderer_get_surface (renderer);
- whole_surface = (cairo_rectangle_int_t) {
- 0, 0,
- gdk_surface_get_width (surface),
- gdk_surface_get_height (surface)
- };
- region = cairo_region_create_rectangle (&whole_surface);
- result = gdk_surface_begin_draw_frame (surface, NULL, region);
- cairo_region_destroy (region);
-
- return result;
-}
-
-
static GdkTexture *
gsk_broadway_renderer_render_texture (GskRenderer *self,
GskRenderNode *root,
}
static void
-gsk_broadway_renderer_render (GskRenderer *self,
- GskRenderNode *root)
-{
- GdkSurface *surface = gsk_renderer_get_surface (self);
- GArray *nodes = g_array_new (FALSE, FALSE, sizeof(guint32));
- GPtrArray *node_textures = g_ptr_array_new_with_free_func (g_object_unref);
+gsk_broadway_renderer_render (GskRenderer *self,
+ GskRenderNode *root,
+ const cairo_region_t *update_area)
+{
+ GArray *nodes;
+ GPtrArray *node_textures;
+ cairo_region_t *whole;
+ GdkDrawingContext *context;
+ GdkSurface *surface;
+ surface = gsk_renderer_get_surface (self);
+ whole = cairo_region_create_rectangle (&(cairo_rectangle_int_t) {
+ 0, 0,
+ gdk_surface_get_width (surface),
+ gdk_surface_get_height (surface)
+ });
+ context = gdk_surface_begin_draw_frame (surface, NULL, whole);
+ cairo_region_destroy (whole);
+
+ nodes = g_array_new (FALSE, FALSE, sizeof(guint32));
+ node_textures = g_ptr_array_new_with_free_func (g_object_unref);
gsk_broadway_renderer_add_node (self, nodes, node_textures, root, 0, 0);
gdk_broadway_surface_set_nodes (surface, nodes, node_textures);
g_array_unref (nodes);
g_ptr_array_unref (node_textures);
+
+ gdk_surface_end_draw_frame (surface, context);
}
static void
{
GskRendererClass *renderer_class = GSK_RENDERER_CLASS (klass);
- renderer_class->begin_draw_frame = gsk_broadway_renderer_begin_draw_frame;
renderer_class->realize = gsk_broadway_renderer_realize;
renderer_class->unrealize = gsk_broadway_renderer_unrealize;
renderer_class->render = gsk_broadway_renderer_render;
}
static void
-gsk_cairo_renderer_render (GskRenderer *renderer,
- GskRenderNode *root)
+gsk_cairo_renderer_render (GskRenderer *renderer,
+ GskRenderNode *root,
+ const cairo_region_t *region)
{
- GdkDrawingContext *context = gsk_renderer_get_drawing_context (renderer);
GdkSurface *surface = gsk_renderer_get_surface (renderer);
-
+ GdkDrawingContext *context;
cairo_t *cr;
+ context = gdk_surface_begin_draw_frame (surface, NULL, region);
cr = gdk_drawing_context_get_cairo_context (context);
g_return_if_fail (cr != NULL);
#endif
gsk_cairo_renderer_do_render (renderer, cr, root);
+
+ gdk_surface_end_draw_frame (surface, context);
}
static void
GObject parent_instance;
GdkSurface *surface;
- GdkDrawingContext *drawing_context;
GskRenderNode *root_node;
GdkDisplay *display;
enum {
PROP_SURFACE = 1,
PROP_DISPLAY,
- PROP_DRAWING_CONTEXT,
N_PROPS
};
return NULL;
}
-static GdkDrawingContext *
-gsk_renderer_real_begin_draw_frame (GskRenderer *self,
- const cairo_region_t *region)
-{
- GskRendererPrivate *priv = gsk_renderer_get_instance_private (self);
-
- return gdk_surface_begin_draw_frame (priv->surface,
- NULL,
- region);
-}
-
-static void
-gsk_renderer_real_end_draw_frame (GskRenderer *self,
- GdkDrawingContext *context)
-{
- GskRendererPrivate *priv = gsk_renderer_get_instance_private (self);
-
- gdk_surface_end_draw_frame (priv->surface,
- context);
-}
-
static void
-gsk_renderer_real_render (GskRenderer *self,
- GskRenderNode *root)
+gsk_renderer_real_render (GskRenderer *self,
+ GskRenderNode *root,
+ const cairo_region_t *region)
{
GSK_RENDERER_WARN_NOT_IMPLEMENTED_METHOD (self, render);
}
g_value_set_object (value, priv->surface);
break;
- case PROP_DRAWING_CONTEXT:
- g_value_set_object (value, priv->drawing_context);
- break;
-
case PROP_DISPLAY:
g_value_set_object (value, priv->display);
break;
klass->realize = gsk_renderer_real_realize;
klass->unrealize = gsk_renderer_real_unrealize;
- klass->begin_draw_frame = gsk_renderer_real_begin_draw_frame;
- klass->end_draw_frame = gsk_renderer_real_end_draw_frame;
klass->render = gsk_renderer_real_render;
klass->render_texture = gsk_renderer_real_render_texture;
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS);
- /**
- * GskRenderer:drawing-context:
- *
- * The drawing context used when rendering.
- */
- gsk_renderer_properties[PROP_DRAWING_CONTEXT] =
- g_param_spec_object ("drawing-context",
- "Drawing Context",
- "The drawing context used by the renderer",
- GDK_TYPE_DRAWING_CONTEXT,
- G_PARAM_READABLE |
- G_PARAM_STATIC_STRINGS);
-
g_object_class_install_properties (gobject_class, N_PROPS, gsk_renderer_properties);
}
return priv->root_node;
}
-/*< private >
- * gsk_renderer_get_drawing_context:
- * @renderer: a #GskRenderer
- *
- * Retrieves the #GdkDrawingContext used by @renderer.
- *
- * Returns: (transfer none) (nullable): a #GdkDrawingContext
- */
-GdkDrawingContext *
-gsk_renderer_get_drawing_context (GskRenderer *renderer)
-{
- GskRendererPrivate *priv = gsk_renderer_get_instance_private (renderer);
-
- g_return_val_if_fail (GSK_IS_RENDERER (renderer), NULL);
-
- return priv->drawing_context;
-}
-
/**
* gsk_renderer_get_display:
* @renderer: a #GskRenderer
const cairo_region_t *region)
{
GskRendererPrivate *priv = gsk_renderer_get_instance_private (renderer);
+ cairo_region_t *real_region;
g_return_if_fail (GSK_IS_RENDERER (renderer));
g_return_if_fail (priv->is_realized);
if (region == NULL || GSK_RENDERER_DEBUG_CHECK (renderer, FULL_REDRAW))
{
- cairo_region_t *full_surface;
-
- full_surface = cairo_region_create_rectangle (&(GdkRectangle) {
+ real_region = cairo_region_create_rectangle (&(GdkRectangle) {
0, 0,
gdk_surface_get_width (priv->surface),
gdk_surface_get_height (priv->surface)
});
- priv->drawing_context = GSK_RENDERER_GET_CLASS (renderer)->begin_draw_frame (renderer, full_surface);
+ GSK_RENDERER_GET_CLASS (renderer)->render (renderer, root, real_region);
- cairo_region_destroy (full_surface);
+ cairo_region_destroy (real_region);
}
else
- priv->drawing_context = GSK_RENDERER_GET_CLASS (renderer)->begin_draw_frame (renderer, region);
-
- GSK_RENDERER_GET_CLASS (renderer)->render (renderer, root);
+ {
+ GSK_RENDERER_GET_CLASS (renderer)->render (renderer, root, region);
+ }
#ifdef G_ENABLE_DEBUG
if (GSK_RENDERER_DEBUG_CHECK (renderer, RENDERER))
}
#endif
- GSK_RENDERER_GET_CLASS (renderer)->end_draw_frame (renderer, priv->drawing_context);
-
- priv->drawing_context = NULL;
g_clear_pointer (&priv->root_node, gsk_render_node_unref);
}
{
GObjectClass parent_class;
- gboolean (* realize) (GskRenderer *renderer,
- GdkSurface *surface,
- GError **error);
- void (* unrealize) (GskRenderer *renderer);
+ gboolean (* realize) (GskRenderer *renderer,
+ GdkSurface *surface,
+ GError **error);
+ void (* unrealize) (GskRenderer *renderer);
- GdkTexture * (* render_texture) (GskRenderer *renderer,
- GskRenderNode *root,
- const graphene_rect_t *viewport);
- GdkDrawingContext * (* begin_draw_frame) (GskRenderer *renderer,
- const cairo_region_t *region);
- void (* end_draw_frame) (GskRenderer *renderer,
- GdkDrawingContext *context);
- void (* render) (GskRenderer *renderer,
- GskRenderNode *root);
+ GdkTexture * (* render_texture) (GskRenderer *renderer,
+ GskRenderNode *root,
+ const graphene_rect_t *viewport);
+ void (* render) (GskRenderer *renderer,
+ GskRenderNode *root,
+ const cairo_region_t *invalid);
};
-gboolean gsk_renderer_is_realized (GskRenderer *renderer);
+gboolean gsk_renderer_is_realized (GskRenderer *renderer);
GskRenderNode * gsk_renderer_get_root_node (GskRenderer *renderer);
-GdkDrawingContext * gsk_renderer_get_drawing_context (GskRenderer *renderer);
GskProfiler * gsk_renderer_get_profiler (GskRenderer *renderer);
-GskDebugFlags gsk_renderer_get_debug_flags (GskRenderer *renderer);
-void gsk_renderer_set_debug_flags (GskRenderer *renderer,
- GskDebugFlags flags);
+GskDebugFlags gsk_renderer_get_debug_flags (GskRenderer *renderer);
+void gsk_renderer_set_debug_flags (GskRenderer *renderer,
+ GskDebugFlags flags);
G_END_DECLS
static void
gsk_vulkan_render_setup (GskVulkanRender *self,
GskVulkanImage *target,
- const graphene_rect_t *rect)
+ const graphene_rect_t *rect,
+ const cairo_region_t *clip)
{
GdkSurface *window = gsk_renderer_get_surface (self->renderer);
{
self->viewport = *rect;
self->scale_factor = 1;
- self->clip = cairo_region_create_rectangle (&(cairo_rectangle_int_t) {
- 0, 0,
- gsk_vulkan_image_get_width (target),
- gsk_vulkan_image_get_height (target)
- });
}
else
{
self->viewport = GRAPHENE_RECT_INIT (0, 0,
gdk_surface_get_width (window) * self->scale_factor,
gdk_surface_get_height (window) * self->scale_factor);
- self->clip = gdk_drawing_context_get_clip (gsk_renderer_get_drawing_context (self->renderer));
+ }
+ if (clip)
+ {
+ self->clip = cairo_region_reference ((cairo_region_t *) clip);
+ }
+ else
+ {
+ self->clip = cairo_region_create_rectangle (&(cairo_rectangle_int_t) {
+ 0, 0,
+ gsk_vulkan_image_get_width (target),
+ gsk_vulkan_image_get_height (target)
+ });
}
}
void
gsk_vulkan_render_reset (GskVulkanRender *self,
GskVulkanImage *target,
- const graphene_rect_t *rect)
+ const graphene_rect_t *rect,
+ const cairo_region_t *clip)
{
gsk_vulkan_render_cleanup (self);
- gsk_vulkan_render_setup (self, target, rect);
+ gsk_vulkan_render_setup (self, target, rect, clip);
}
GskRenderer *
ceil (viewport->size.width),
ceil (viewport->size.height));
- gsk_vulkan_render_reset (render, image, viewport);
+ gsk_vulkan_render_reset (render, image, viewport, NULL);
gsk_vulkan_render_add_node (render, root);
}
static void
-gsk_vulkan_renderer_render (GskRenderer *renderer,
- GskRenderNode *root)
+gsk_vulkan_renderer_render (GskRenderer *renderer,
+ GskRenderNode *root,
+ const cairo_region_t *region)
{
GskVulkanRenderer *self = GSK_VULKAN_RENDERER (renderer);
GskVulkanRender *render;
+ GdkDrawingContext *context;
+ GdkSurface *surface;
+ cairo_region_t *clip;
#ifdef G_ENABLE_DEBUG
GskProfiler *profiler;
gint64 cpu_time;
#endif
+ surface = gsk_renderer_get_surface (renderer);
+
#ifdef G_ENABLE_DEBUG
profiler = gsk_renderer_get_profiler (renderer);
gsk_profiler_counter_set (profiler, self->profile_counters.fallback_pixels, 0);
gsk_profiler_timer_begin (profiler, self->profile_timers.cpu_time);
#endif
+ context = gdk_surface_begin_draw_frame (surface,
+ GDK_DRAW_CONTEXT (self->vulkan),
+ region);
render = self->render;
- gsk_vulkan_render_reset (render, self->targets[gdk_vulkan_context_get_draw_index (self->vulkan)], NULL);
+ clip = gdk_drawing_context_get_clip (context);
+ gsk_vulkan_render_reset (render, self->targets[gdk_vulkan_context_get_draw_index (self->vulkan)], NULL, clip);
+ cairo_region_destroy (clip);
gsk_vulkan_render_add_node (render, root);
gsk_profiler_push_samples (profiler);
#endif
-}
-
-static GdkDrawingContext *
-gsk_vulkan_renderer_begin_draw_frame (GskRenderer *renderer,
- const cairo_region_t *region)
-{
- GskVulkanRenderer *self = GSK_VULKAN_RENDERER (renderer);
- GdkDrawingContext *result;
-
- result = gdk_surface_begin_draw_frame (gsk_renderer_get_surface (renderer),
- GDK_DRAW_CONTEXT (self->vulkan),
- region);
- return result;
+ gdk_surface_end_draw_frame (surface, context);
}
static void
renderer_class->unrealize = gsk_vulkan_renderer_unrealize;
renderer_class->render = gsk_vulkan_renderer_render;
renderer_class->render_texture = gsk_vulkan_renderer_render_texture;
- renderer_class->begin_draw_frame = gsk_vulkan_renderer_begin_draw_frame;
}
static void
gboolean gsk_vulkan_render_is_busy (GskVulkanRender *self);
void gsk_vulkan_render_reset (GskVulkanRender *self,
GskVulkanImage *target,
- const graphene_rect_t *rect);
+ const graphene_rect_t *rect,
+ const cairo_region_t *clip);
GskRenderer * gsk_vulkan_render_get_renderer (GskVulkanRender *self);